package com.three.common.handler;

import com.google.protobuf.InvalidProtocolBufferException;
import com.three.api.MessageHandler;
import com.three.api.connection.Connection;
import com.three.api.protocol.Packet;
import com.three.common.message.base.BaseMessage;
import com.three.tools.common.Profiler;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 消息处理基础类
 * Created by mathua on 2017/5/30.
 */
public class MessageBaseHandler<T extends BaseMessage> implements MessageHandler {

    private final Class<? extends BaseMessage> clazz;// message的class
    private final Method method;// 消息模块的一个handler方法
    private final Object obj;// 消息模块(module)类
    private final boolean shouldVerifyIdentity;

    public MessageBaseHandler(Object obj, Method method, Class<? extends BaseMessage> clazz, boolean shouldVerifyIdentity) {
        this.obj = obj;
        this.method = method;
        this.clazz = clazz;
        this.shouldVerifyIdentity = shouldVerifyIdentity;
    }

    /**
     * 数据包解码
     *
     * @param packet     要解码的数据包
     * @param connection 数据包来源
     * @return 返回数据包对应的消息
     */
    public T decode(Packet packet, Connection connection) {
        try {
            Constructor c = clazz.getDeclaredConstructor(new Class[] {Packet.class, Connection.class});
            c.setAccessible(true);
            return (T) c.newInstance(new Object[]{packet, connection});
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public void handle(Packet packet, Connection connection) throws InvalidProtocolBufferException, InvocationTargetException, IllegalAccessException {
        Profiler.enter("time cost on [message decode]");
        T t = decode(packet, connection);
        if (t != null) t.decodeBody();
        Profiler.release();// 数据包解码计时

        if (t != null) {
            Profiler.enter("time cost on [handle]");
            method.invoke(obj, t);
            Profiler.release();// 数据包处理计时
        }
    }

    public void handler(BaseMessage message) throws InvocationTargetException, IllegalAccessException {
        Profiler.enter("time cost on [message decode]");
        T t = (T) message;
        Profiler.release();// 数据包解码计时

        if (t != null) {
            Profiler.enter("time cost on [handle]");
            method.invoke(obj, t);
            Profiler.release();// 数据包处理计时
        }
    }

    public boolean isShouldVerifyIdentity() {
        return shouldVerifyIdentity;
    }
}
